/**
 * Copyright (C) 2021 All rights reserved.
 *
 * @file dp_trie_string2.h
 * @author Wang Haibin
 * @email wanghaibin@qiyi.com
 * @date Thu Jul 25 10:51:23 CST 2024
 * @brief 支持字符串模糊搜索*和?的字典树,嵌套cidr
 */
#pragma once

#include <iostream>
#include <memory>
#include <string.h>
#include <string>
#include <unordered_map>
#include <vector>

#include "dp_trie_value.h"

namespace dp {

class dp_trie_cidr;
// 树节点
class dp_trie_string2_node {
public:
    std::unordered_map<char, std::shared_ptr<dp_trie_string2_node>> child_;
    std::shared_ptr<dp_trie_string2_node> parent_;
    std::shared_ptr<dp_trie_cidr> rule_obj_;  // 规则对象
    bool bend_;                               // 是否为规则终点
    char c_;  // 当前节点的字符 ,根节点为0

    dp_trie_string2_node(char c, std::shared_ptr<dp_trie_string2_node>& parent);
    ~dp_trie_string2_node();

    /**
     * @brief 获取树关键字列表
     *
     */
    void get_tree_str(std::string& str);

    /**
     * @brief 设置完整规则
     *
     */
    void set_rule(const std::string& rule) { rule_ = rule; }
    const std::string& get_rule() const { return rule_; }

private:
    std::string rule_;  // 当bend_为true时的完整规则
};

// 字典树
class dp_trie_string2 : public dp_trie_value {
public:
    dp_trie_string2();
    ~dp_trie_string2();

    /**
     * @brief 插入规则
     *
     * @param rule 规则字符串
     * @param rule_obj 规则对应的对象
     * @param back true则rule构建时从后向前构建, 否则从前向后构建
     *
     */
    bool insert(const std::string& rule,
                std::shared_ptr<dp_trie_cidr>& rule_obj);

    /**
     * @brief 内容是否包含key, 不用查找直接返回true
     *
     * @param params 当trie嵌套时params包含了每一级的参数.每级pop自己需要的参数
     * @return true 包含, false 不包含
     */
    virtual bool search(std::shared_ptr<dp_trie_value>& value,
                        std::stack<std::string>& params);

    /**
     * @brief 根据str查找是否存在对应的规则
     *
     * @param value 非空时返回规则对应内容
     * @param str 要查找的字符串
     * @param params 传递给子节点的参数列表
     * @parm dn_rule 非空时返回dn命中规则字符串
     * @return true 存在,false 不存在
     */
    bool search(std::shared_ptr<dp_trie_value>& value, const std::string& str,
                std::stack<std::string>& params, std::string* dn_rule);

    /**
     * @brief 打印树信息
     *
     */
    void printf_root();

private:
    /**
     * @brief 模糊查找
     *
     * @param node 开始查找节点
     * @param str 要查找的字符串
     * @apram str_rule 返回str命中的规则字符串
     */
    bool fuzzy_match(std::shared_ptr<dp_trie_value>& value,
                     std::shared_ptr<dp_trie_string2_node>& node,
                     const char* str, std::stack<std::string>& params,
                     std::string* str_rule);
    /**
     * @brief 匹配查找
     *
     * @param value 返回对应的规则内容
     * @param node 开始查找节点
     * @param str 要查找的字符串
     * @param params 递归查找时的其他的参数列表
     * @apram str_rule 返回str命中的规则字符串
     * @return true 找到节点, false 未找到节点
     */
    bool match(std::shared_ptr<dp_trie_value>& value,
               std::shared_ptr<dp_trie_string2_node>& node,
               const std::string& str, std::stack<std::string>& params,
               std::string* str_rule);

private:
    std::shared_ptr<dp_trie_string2_node> root_;
    std::vector<std::string> rules_;
};

}  // namespace dp
